﻿//---------------------------------------------------------------------------
// <summary>
// Plugin to extract dynamic data from InfoPath requests
// and substitute it in for InfoPath post backs
// </summary>
//---------------------------------------------------------------------------

namespace InfoPathExtractionRules
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using Microsoft.VisualStudio.TestTools.WebTesting;

    /// <summary>
    /// Extracts CurrentFormData from InfoPath responses.
    /// Substitutes the dynamic data into InfoPath postback requests.
    /// </summary>
    public class ExtractAndSubstituteDynamicInfoPathData : WebTestPlugin
    {
        /// <summary>
        /// String used to identify an InfoPath invocation and full page postback.
        /// </summary>
        private string invocationPath;

        /// <summary>
        /// Maps to the state of the ParseStringBodyAsEventLogList property.
        /// </summary>
        private Format format = InfoPathExtractionRules.Format.FormsServicesPostBackBody;

        /// <summary>
        /// Gets or sets a String used to identify an InfoPath invocation and full page postback.
        /// </summary>
        /// <value>String used to identify an InfoPath invocation and full page postback.</value>
        public string InvocationPath
        {
            get
            {
                return this.invocationPath;
            }

            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    this.invocationPath = IPExtractionUtility.DefaultFormServerPath;
                }
                else
                {
                    this.invocationPath = value;
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the plug-in should parse
        /// the string body as an InfoPath postback body.
        /// </summary>
        /// <value>
        /// If false, parse the string body as an InfoPath postback body.
        /// If true, parse the string body as a list of InfoPath event logs.
        /// </value>
        public bool ParseStringBodyAsEventLogList
        {
            get
            {
                return this.format == InfoPathExtractionRules.Format.EventLogList;
            }

            set
            {
                this.format = value ?
                    InfoPathExtractionRules.Format.EventLogList
                     :
                    InfoPathExtractionRules.Format.FormsServicesPostBackBody;
            }
        }

        /// <summary>
        /// Substitutes extracted CurrentFormData for InfoPath postbacks requests.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A PreRequestEventArgs that contains the event data.</param>
        public override void PreRequest(object sender, PreRequestEventArgs e)
        {
            base.PreRequest(sender, e);

            WebTestRequest req = e.Request;
            WebTestContext context = e.WebTest.Context;

            if (IPExtractionUtility.IsPartialPostBack(req))
            {
                StringHttpBody body = (StringHttpBody)e.Request.Body;
                body.BodyString = IPExtractionUtility.SubstituteCurrentFormData(body.BodyString, context, this.format);
            }
            else if (IPExtractionUtility.IsFullPagePostBack(req, this.invocationPath))
            {
                FormPostHttpBody postBackBody = (FormPostHttpBody)e.Request.Body;
                foreach (FormPostParameter parameter in postBackBody.FormPostParameters)
                {
                    if (parameter.Name.Contains(IPExtractionUtility.EventLogFormPostBackParameterName))
                    {
                        parameter.Value = IPExtractionUtility.SubstituteCurrentFormData(parameter.Value, context, this.format);
                    }
                }
            }
        }

        /// <summary>
        /// Extracts CurrentFormData from InfoPath responses.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">A PostRequestEventArgs that contains the event data.</param>
        public override void PostRequest(object sender, PostRequestEventArgs e)
        {
            base.PostRequest(sender, e);
            WebTestRequest req = e.Request;

            if (IPExtractionUtility.IsPartialPostBack(req) ||
                IPExtractionUtility.IsInvocation(req, this.invocationPath) ||
                IPExtractionUtility.IsFullPagePostBack(req, this.invocationPath))
            {
                IPExtractionUtility.ExtractCurrentFormData(e.Response, e.WebTest.Context);
            }
        }
    }
}
